package com.kynnnn.cloud.springboot_quartz.service;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.kynnnn.cloud.springboot_quartz.constant.ScheduleJobStatus;
import com.kynnnn.cloud.springboot_quartz.entity.ScheduleJobConfig;
import com.kynnnn.cloud.springboot_quartz.exception.ScheduleJobException;
import com.kynnnn.cloud.springboot_quartz.mapper.ScheduleJobMapper;
import com.kynnnn.cloud.springboot_quartz.vo.CommonResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;

import java.util.Date;
import java.util.List;
import java.util.Objects;

/**
 * @author Zhudiwei
 * @date 2021/10/13
 **/
@Service
@Slf4j
public class ScheduleJobService extends ServiceImpl<ScheduleJobMapper, ScheduleJobConfig> {

    @Autowired
    private QuartzService quartzService;

    /**
     * <h2>新增定时任务</h2>
     *
     * @param jobConfig
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public CommonResponse<?> insert(ScheduleJobConfig jobConfig) {

        // 由于[任务名称+任务组]的组合不可以重复，所以预先做校验
        List<ScheduleJobConfig> list = this.lambdaQuery()
                .eq(ScheduleJobConfig::getJobName, jobConfig.getJobName())
                .eq(ScheduleJobConfig::getJobGroupName, jobConfig.getJobGroupName())
                .list();
        if (!list.isEmpty()) {
            throw new RuntimeException(String.format("以[%s]为任务名且[%s]为任务组名的定时任务已存在！", jobConfig.getJobName(), jobConfig.getJobGroupName()));
        }

        // 新增定时任务配置
        jobConfig.setCreateTime(new Date());
        this.save(jobConfig);

        // 如果状态是开启状态则向Quartz中新增定时任务
        if (jobConfig.getStatus().equals(ScheduleJobStatus.RUN)) {
            quartzService.add(jobConfig);
        }

        return CommonResponse.success();
    }

    /**
     * <h2>修改定时任务</h2>
     *
     * @param jobConfig
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public CommonResponse<?> update(@RequestBody ScheduleJobConfig jobConfig) {

        // 由于[任务名称+任务组]的组合不可以重复，所以预先做校验
        ScheduleJobConfig one = this.lambdaQuery()
                .eq(ScheduleJobConfig::getJobName, jobConfig.getJobName())
                .eq(ScheduleJobConfig::getJobGroupName, jobConfig.getJobGroupName())
                .one();
        if (!one.getId().equals(jobConfig.getId())) {
            throw new RuntimeException(String.format("以[%s]为任务名且[%s]为任务组名的定时任务已存在！", jobConfig.getJobName(), jobConfig.getJobGroupName()));
        }

        // 更新定时任务配置
        jobConfig.setModifyTime(new Date());
        this.updateById(jobConfig);

        Integer status = jobConfig.getStatus();

        switch (status) {
            // 如果任务状态为【开启】，则更新任务
            case ScheduleJobStatus.RUN:
                quartzService.update(jobConfig);
                break;
            // 如果任务状态为【暂停】，则暂停任务
            case ScheduleJobStatus.PAUSE:
                quartzService.pause(jobConfig);
                break;
            default:
                return CommonResponse.success();
        }

        return CommonResponse.success();
    }

    /**
     * <h2>删除定时任务</h2>
     *
     * @param id
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public CommonResponse<?> delete(@PathVariable String id) {

        // 删除定时任务配置
        ScheduleJobConfig jobConfig = this.getById(id);
        this.removeById(id);

        // 删除Quartz中的任务信息
        this.quartzService.delete(jobConfig);

        return CommonResponse.success();
    }

    /**
     * <h2>暂停定时任务</h2>
     *
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public CommonResponse<?> pause(String configId) {

        // 根据Id查询唯一的定时任务配置
        ScheduleJobConfig jobConfig = this.getById(configId);
        if (Objects.isNull(jobConfig)) {
            throw new ScheduleJobException(String.format("没有此Id：[%s]对应的定时任务配置", configId));
        }

        // 更新定时任务配置的状态
        jobConfig.setStatus(ScheduleJobStatus.PAUSE);
        this.updateById(jobConfig);

        // 暂停Quartz中的定时任务
        this.quartzService.pause(jobConfig);

        return CommonResponse.success();
    }

    /**
     * <h2>恢复定时任务</h2>
     *
     * @param configId
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public CommonResponse<?> resume(String configId) {

        // 根据Id查询唯一的定时任务配置
        ScheduleJobConfig jobConfig = this.getById(configId);
        if (Objects.isNull(jobConfig)) {
            throw new ScheduleJobException(String.format("没有此Id：[%s]对应的定时任务配置", configId));
        }

        // 更新定时任务配置的状态
        jobConfig.setStatus(ScheduleJobStatus.RUN);
        this.updateById(jobConfig);

        // 恢复Quartz中的定时任务
        this.quartzService.resume(jobConfig);

        return CommonResponse.success();
    }

}
